using Microsoft.Expression.Drawing.Core;
using Microsoft.Expression.Media;
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
namespace Microsoft.Expression.Shapes
{
	public abstract class PrimitiveShape : Path, IGeometrySourceParameters, IShape
	{
		private IGeometrySource geometrySource;
		private bool realizeGeometryScheduled;
		private static readonly DependencyProperty StretchListenerProperty = DependencyProperty.Register("StretchListener", typeof(Stretch), typeof(PrimitiveShape), new DrawingPropertyMetadata(1, DrawingPropertyMetadataOptions.AffectsRender));
		private static readonly DependencyProperty ThicknessListenerProperty = DependencyProperty.Register("ThicknessListener", typeof(double), typeof(PrimitiveShape), new DrawingPropertyMetadata(1.0, DrawingPropertyMetadataOptions.AffectsRender));
		public event EventHandler RenderedGeometryChanged;
		private IGeometrySource GeometrySource
		{
			get
			{
				IGeometrySource arg_19_0;
				if ((arg_19_0 = this.geometrySource) == null)
				{
					arg_19_0 = (this.geometrySource = this.CreateGeometrySource());
				}
				return arg_19_0;
			}
		}
		public Geometry RenderedGeometry
		{
			get
			{
				return this.GeometrySource.Geometry;
			}
		}
		public Thickness GeometryMargin
		{
			get
			{
				if (this.Data == null)
				{
					return default(Thickness);
				}
				return this.GeometrySource.LogicalBounds.Subtract(this.Data.get_Bounds());
			}
		}
		public Geometry Data
		{
			get
			{
				return (Geometry)base.GetValue(Path.DataProperty);
			}
			set
			{
				base.SetValue(Path.DataProperty, value);
			}
		}
		Stretch IGeometrySourceParameters.Stretch
		{
			get
			{
				return base.get_Stretch();
			}
		}
		Brush IGeometrySourceParameters.Stroke
		{
			get
			{
				return base.get_Stroke();
			}
		}
		double IGeometrySourceParameters.StrokeThickness
		{
			get
			{
				return base.get_StrokeThickness();
			}
		}
		Brush IShape.Fill
		{
			get
			{
				return base.get_Fill();
			}
			set
			{
				base.set_Fill(value);
			}
		}
		Brush IShape.Stroke
		{
			get
			{
				return base.get_Stroke();
			}
			set
			{
				base.set_Stroke(value);
			}
		}
		double IShape.StrokeThickness
		{
			get
			{
				return base.get_StrokeThickness();
			}
			set
			{
				base.set_StrokeThickness(value);
			}
		}
		Stretch IShape.Stretch
		{
			get
			{
				return base.get_Stretch();
			}
			set
			{
				base.set_Stretch(value);
			}
		}
		protected abstract IGeometrySource CreateGeometrySource();
		public void InvalidateGeometry(InvalidateGeometryReasons reasons)
		{
			if (this.GeometrySource.InvalidateGeometry(reasons))
			{
				base.InvalidateArrange();
				if (Application.get_Current() != null && Application.get_Current().get_RootVisual() != null && (bool)Application.get_Current().get_RootVisual().GetValue(DesignerProperties.IsInDesignModeProperty) && (reasons & InvalidateGeometryReasons.IsAnimated) != (InvalidateGeometryReasons)0 && this.GeometrySource.UpdateGeometry(this, this.ActualBounds()) && !this.realizeGeometryScheduled)
				{
					this.realizeGeometryScheduled = true;
					base.add_LayoutUpdated(new EventHandler(this.OnLayoutUpdated));
				}
			}
		}
		protected override Size MeasureOverride(Size availableSize)
		{
			return new Size(base.get_StrokeThickness(), base.get_StrokeThickness());
		}
		protected override Size ArrangeOverride(Size finalSize)
		{
			if (this.GeometrySource.UpdateGeometry(this, finalSize.Bounds()) && !this.realizeGeometryScheduled)
			{
				this.realizeGeometryScheduled = true;
				base.add_LayoutUpdated(new EventHandler(this.OnLayoutUpdated));
			}
			base.ArrangeOverride(finalSize);
			return finalSize;
		}
		private void OnLayoutUpdated(object sender, EventArgs e)
		{
			this.realizeGeometryScheduled = false;
			base.remove_LayoutUpdated(new EventHandler(this.OnLayoutUpdated));
			this.RealizeGeometry();
		}
		private void RealizeGeometry()
		{
			this.Data = this.GeometrySource.Geometry.CloneCurrentValue();
			if (this.RenderedGeometryChanged != null)
			{
				this.RenderedGeometryChanged.Invoke(this, EventArgs.Empty);
			}
		}
		protected PrimitiveShape()
		{
			this.SetListenerBinding(PrimitiveShape.StretchListenerProperty, "Stretch");
			this.SetListenerBinding(PrimitiveShape.ThicknessListenerProperty, "StrokeThickness");
		}
		private void SetListenerBinding(DependencyProperty targetProperty, string sourceProperty)
		{
			Binding binding = new Binding(sourceProperty);
			binding.set_Source(this);
			binding.set_Mode(1);
			base.SetBinding(targetProperty, binding);
		}
	}
}
